package com.example.njupt.log;

import androidx.annotation.IntRange;

import com.google.gson.Gson;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.List;

import static com.example.njupt.constant.LogConstants.BOTTOM_BORDER;
import static com.example.njupt.constant.LogConstants.LINE_SEP;
import static com.example.njupt.constant.LogConstants.MIDDLE_BORDER;
import static com.example.njupt.constant.LogConstants.MIN_STACK_OFFSET;
import static com.example.njupt.constant.LogConstants.NULL;
import static com.example.njupt.constant.LogConstants.TOP_BORDER;

/**
 * Author:      mwang
 * Create Date: Created in 2021/5/27 19:05
 * Update Date:
 * Modified By:
 * Description: 日志装饰器
 */
public class LogHelper {

    public String create(Object object) {
        return decoration(examineBody(0, object));
    }

    public String createJson(String jsonObject) {
        if (jsonObject == null) return NULL;
        if (jsonObject instanceof String) {
            return decoration(formatJson(jsonObject));
        }
        return decoration(formatJson(new Gson().toJson(jsonObject)));
    }

    private String formatJson(String jsonObject) {
        if (jsonObject.startsWith("{")) {
            try {
                jsonObject = new JSONObject(jsonObject).toString(4);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else if (jsonObject.startsWith("[")) {
            try {
                jsonObject = new JSONArray(jsonObject).toString(4);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return jsonObject;
    }

    private String decoration(String examineBody) {
        return TOP_BORDER + LINE_SEP +
                examineHeader() + LINE_SEP +
                MIDDLE_BORDER + LINE_SEP +
                examineBody + LINE_SEP +
                BOTTOM_BORDER;
    }

    private String examineHeader() {
        StackTraceElement[] stackTraceElement = new Throwable().getStackTrace();
        int stackOffset = getOffset(stackTraceElement);
        StackTraceElement stack = stackTraceElement[stackOffset];
        String fileName = stack.getFileName();
        String name = Thread.currentThread().getName();
        return "thread：" + name + "--" + stack.getMethodName() + "\n" + fileName + "：" + stack.getLineNumber();
    }

    private int getOffset(StackTraceElement[] stackTraceElement) {
        for (int i = MIN_STACK_OFFSET; i < stackTraceElement.length; i++) {
            StackTraceElement stack = stackTraceElement[i];
            String name = stack.getClassName();
            if (!name.equals(LogHelper.class.getName()) && !name.equals(NjuptLogger.class.getName())) {
                return i;
            }
        }
        return -1;
    }

    private String examineBody(@IntRange(from = 0) int level, Object object) {
        if (object == null) {
            return NULL;
        } else if (object instanceof String) {
            return formatJson((String) object);
        } else if (object instanceof List) {
            return formatList(level, object);
        } else {
            return object.toString();
        }
    }

    private String formatList(int level, Object object) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 1; i < level; i++) {
            stringBuilder.append("    ");
        }
        StringBuilder stringBuilder1 = new StringBuilder();
        stringBuilder.append("[");
        if (object instanceof List) {
            List<Object> list = (List<Object>) object;
            for (int i = 0; i < list.size(); i++) {
                stringBuilder1.append(LINE_SEP)
                        .append(stringBuilder).append("    ")
                        .append(examineBody(level + 1, list.get(i)));
                if (i != list.size() - 1) {
                    stringBuilder1.append(",");
                }
                stringBuilder1.append("]");
            }
        }
        return stringBuilder1.toString();
    }
}
